package org.dromara.solonplugins.bee.integration;

import org.noear.solon.core.AopContext;
import org.noear.solon.core.BeanWrap;
import org.noear.solon.core.Props;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.teasoft.beex.config.BeePro;
import org.teasoft.beex.config.BeeProCache;
import org.teasoft.beex.config.BeeProCacheRedis;
import org.teasoft.beex.config.BeeProDb;
import org.teasoft.beex.config.BeeProGenid;
import org.teasoft.beex.config.BeeProMoreTable;
import org.teasoft.beex.config.BeeProMultiDS;
import org.teasoft.beex.config.BeeProNaming;
import org.teasoft.beex.config.BeeProPearFlowerId;
import org.teasoft.beex.config.BeeProProfiles;
import org.teasoft.beex.config.BeeProReturnStringList;
import org.teasoft.beex.config.BeeProSelectJson;
import org.teasoft.beex.config.BeeProSharding;
import org.teasoft.beex.config.BeeProShowSql;
import org.teasoft.beex.config.ManageConfig;
import org.teasoft.beex.osql.ObjSQLRichExt;
import org.teasoft.beex.transaction.TranHandler;
import org.teasoft.honey.osql.core.CallableSqlLib;
import org.teasoft.honey.osql.core.ConditionImpl;
import org.teasoft.honey.osql.core.MapSqlImpl;
import org.teasoft.honey.osql.core.MapSuidImpl;
import org.teasoft.honey.osql.core.MongodbObjSQL;
import org.teasoft.honey.osql.core.MongodbObjSQLRich;
import org.teasoft.honey.osql.core.MoreObjSQL;
import org.teasoft.honey.osql.core.MoreObjectToSQL;
import org.teasoft.honey.osql.core.ObjSQL;
import org.teasoft.honey.osql.core.ObjSQLRich;
import org.teasoft.honey.osql.core.ObjectToSQL;
import org.teasoft.honey.osql.core.ObjectToSQLRich;
import org.teasoft.honey.osql.core.PreparedSqlLib;
import org.teasoft.honey.osql.core.SqlLib;
import org.teasoft.honey.osql.serviceimpl.ObjSQLRichServiceImpl;
import org.teasoft.honey.osql.serviceimpl.ObjSQLServiceImpl;

/**
 * 用于定义
 */
public class BeePropertiesManager {
	private static final Logger logger = LoggerFactory.getLogger(BeePropertiesManager.class);

	private AopContext context;

	private final Props props;

	private ManageConfig manageConfig1;

	public BeePropertiesManager(AopContext context) {
		this.context = context;
		this.props = context.cfg();
		this.manageConfig1 = new ManageConfig();
	}

	/**
	 * 注入各种bean
	 */
	public void getBean() {
		getBeePro();
		getBeeProCache();
		getBeeProCacheRedis();
		getBeeProDb();
		getBeeProProfiles();
		getBeeProGenid();
		getBeeProMoreTable();
		getBeeProMultiDS();
		getBeeProSharding();
		getBeeProNaming();
		getBeeProPearFlowerId();
		getBeeProReturnStringList();
		getBeeProSelectJson();
		getBeeProShowSql();

		// 最后注入ManageConfig
		manageConfig1.updateConfig();
		context.wrapAndPut(ManageConfig.class, manageConfig1);
	}

	/**
	 * 参考beeContext.xml
	 */
	public void xmlBean() {
		BeanWrap beeSql = context.wrapAndPut(SqlLib.class, new SqlLib());

		BeanWrap objToSQL = context.wrapAndPut(ObjectToSQL.class, new ObjectToSQL());

		BeanWrap objToSQLRich = context.wrapAndPut(ObjectToSQLRich.class, new ObjectToSQLRich());

		BeanWrap moreObjToSQL = context.wrapAndPut(MoreObjectToSQL.class, new MoreObjectToSQL());

		ObjSQL os = new ObjSQL();
		os.setBeeSql(beeSql.raw());
		os.setObjToSQL(objToSQL.raw());
		BeanWrap suid = context.wrapAndPut(ObjSQL.class, os);

		ObjSQLRich osr = new ObjSQLRich();
		osr.setObjToSQLRich(objToSQLRich.raw());
		BeanWrap suidRich = context.wrapAndPut(ObjSQLRich.class, osr);

		BeanWrap suidRichExt = context.wrapAndPut(ObjSQLRichExt.class, new ObjSQLRichExt());

		PreparedSqlLib ps = new PreparedSqlLib();
		ps.setBeeSql(beeSql.raw());
		BeanWrap preparedSql = context.wrapAndPut(PreparedSqlLib.class, ps);

		BeanWrap callableSql = context.wrapAndPut(CallableSqlLib.class, new CallableSqlLib());

		MoreObjSQL mos = new MoreObjSQL();
		mos.setBeeSql(beeSql.raw());
		mos.setMoreObjToSQL(moreObjToSQL.raw());
		BeanWrap moreTable = context.wrapAndPut(MoreObjSQL.class, mos);

		MapSuidImpl msi = new MapSuidImpl();
		msi.setBeeSql(beeSql.raw());
		BeanWrap mapSuid = context.wrapAndPut(MapSuidImpl.class, msi);

		BeanWrap condition = context.wrapAndPut(ConditionImpl.class, new ConditionImpl());

		BeanWrap mapSql = context.wrapAndPut(MapSqlImpl.class, new MapSqlImpl());

		ObjSQLServiceImpl ossi = new ObjSQLServiceImpl();
		ossi.setSuid(suid.raw());
		BeanWrap objSQLService = context.wrapAndPut(ObjSQLServiceImpl.class, ossi);

		ObjSQLRichServiceImpl osrsi = new ObjSQLRichServiceImpl();
		osrsi.setSuidRich(suidRich.raw());
		BeanWrap objSQLRichService = context.wrapAndPut(ObjSQLRichServiceImpl.class, osrsi);

		//TranHandler 依赖于aspectj进行事务处理
//		BeanWrap tranHandler = context.wrapAndPut(TranHandler.class, new TranHandler()); //事务由solon托管
		
		mongoXmlBean();
	}

	private void mongoXmlBean() {
		// for Mongodb
		BeanWrap mongoSuid = context.wrapAndPut(MongodbObjSQL.class, new MongodbObjSQL());

		BeanWrap mongoSuidRich = context.wrapAndPut(MongodbObjSQLRich.class, new MongodbObjSQLRich());

		ObjSQLServiceImpl mossi = new ObjSQLServiceImpl();
		mossi.setSuid(mongoSuid.raw());
		BeanWrap mongodbObjSQLService = context.wrapAndPut(ObjSQLServiceImpl.class, mossi);

		ObjSQLRichServiceImpl mosrsi = new ObjSQLRichServiceImpl();
		mosrsi.setSuidRich(mongoSuidRich.raw());
		BeanWrap mongodbObjSQLRichService = context.wrapAndPut(ObjSQLRichServiceImpl.class, mosrsi);
	
//		context.wrapAndPut(MongodbObjSQLRichExt.class,new MongodbObjSQLRichExt());
	}

	private void getBeePro() {
		try {
			Class.forName("org.teasoft.beex.config.BeePro");
			BeePro b = props.getBean("bee.osql", BeePro.class);
//			context.wrapAndPut(BeePro.class, b);

			manageConfig1.setBeePro(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProCache() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProCache");
			BeeProCache b = props.getBean("bee.osql.cache", BeeProCache.class);
//			context.wrapAndPut(BeeProCache.class, b);

			manageConfig1.setBeeProCache(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProCacheRedis() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProCacheRedis");
			BeeProCacheRedis b = props.getBean("bee.osql.cache-redis", BeeProCacheRedis.class);
//			context.wrapAndPut(BeeProCacheRedis.class, b);

			manageConfig1.setBeeProCacheRedis(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	@Deprecated
	private void getBeeProDb() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProDb");
			BeeProDb b = props.getBean("bee.db", BeeProDb.class);
			if(b!=null) {
				logger.warn("不建议配置数据源！最多配置bee.db.pagingWithLimitOffset，其他配置默认从solon环境中获取，减少交叉重复配置");
			}
//			context.wrapAndPut(BeeProDb.class, b);

			manageConfig1.setBeeProDb(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	@Deprecated
	private void getBeeProProfiles() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProProfiles");// V1.11
			BeeProProfiles b = props.getBean("bee.profiles", BeeProProfiles.class);
			if(b!=null) {
				logger.warn("不建议使用配置bee.profiles，请使用solon的[环境切换及加载更多配置]");
			}
//			context.wrapAndPut(BeeProProfiles.class, b);

			manageConfig1.setBeeProProfiles(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProGenid() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProGenid");
			BeeProGenid b = props.getBean("bee.distribution.genid", BeeProGenid.class);
//			context.wrapAndPut(BeeProGenid.class, b);

			manageConfig1.setBeeProGenid(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProMoreTable() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProMoreTable");
			BeeProMoreTable b = props.getBean("bee.osql.more-table", BeeProMoreTable.class);
//			context.wrapAndPut(BeeProMoreTable.class, b);

			manageConfig1.setBeeProMoreTable(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProMultiDS() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProMultiDS");
			BeeProMultiDS b = props.getBean("bee.dosql.multi-ds", BeeProMultiDS.class);
//			context.wrapAndPut(BeeProMultiDS.class, b);

			manageConfig1.setBeeProMultiDS(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProSharding() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProSharding");// V2.0
			BeeProSharding b = props.getBean("bee.dosql.sharding", BeeProSharding.class);
//			context.wrapAndPut(BeeProSharding.class, b);

			manageConfig1.setBeeProSharding(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProNaming() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProNaming");
			BeeProNaming b = props.getBean("bee.osql.naming", BeeProNaming.class);
//			context.wrapAndPut(BeeProNaming.class, b);

			manageConfig1.setBeeProNaming(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProPearFlowerId() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProSharding");
			BeeProPearFlowerId b = props.getBean("bee.distribution.pear-flower-id", BeeProPearFlowerId.class);
//			context.wrapAndPut(BeeProPearFlowerId.class, b);

			manageConfig1.setBeeProPearFlowerId(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProReturnStringList() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProReturnStringList");
			BeeProReturnStringList b = props.getBean("bee.osql.return-string-list", BeeProReturnStringList.class);
//			context.wrapAndPut(BeeProReturnStringList.class, b);

			manageConfig1.setBeeProReturnStringList(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProSelectJson() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProSelectJson");
			BeeProSelectJson b = props.getBean("bee.osql.select-json", BeeProSelectJson.class);
//			context.wrapAndPut(BeeProSelectJson.class, b);

			manageConfig1.setBeeProSelectJson(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private void getBeeProShowSql() {
		try {
			Class.forName("org.teasoft.beex.config.BeeProShowSql");
			BeeProShowSql b = props.getBean("bee.osql.show-sql", BeeProShowSql.class);
//			context.wrapAndPut(BeeProShowSql.class, b);

			manageConfig1.setBeeProShowSql(b);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

}
